package config

import (
	"fmt"
	"log"
	"path/filepath"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

// 应用基础配置

// 区块链网络连接配置
type ConnectionConfig struct {
	Profile      string `yaml:"profile"`
	Channel      string `yaml:"channel"`
	Organization string `yaml:"organization"`
	User         string `yaml:"user"`
}

// 链码版本配置
type ChaincodeConfig struct {
	Name    string `mapstructure:"name"`
	Version string `mapstructure:"version"`
}
type AppConfig struct {
	Port     int    `yaml:"port"`
	LogLevel string `yaml:"log_level"`
}

type Config struct {
	App    AppConfig              `yaml:"app"`
	Chains map[string]ChainConfig `yaml:"chains"`
}

// 区块链网络完整配置
type ChainConfig struct {
	Connection ConnectionConfig `yaml:"connection"`
	Chaincodes struct {
		Evidence struct {
			Name    string `yaml:"name"`
			Version string `yaml:"version"`
		} `yaml:"evidence"`
		Assert struct {
			Name    string `yaml:"name"`
			Version string `yaml:"version"`
		} `yaml:"assert"`
	} `yaml:"chaincodes"`
	IsActive bool `yaml:"is_active"`
}

var GlobalConfig Config

// 确保配置中的路径是绝对路径
func resolvePaths() {
	configFile := viper.ConfigFileUsed()
	if configFile == "" {
		log.Println("警告: 无法确定配置文件位置")
		return
	}
	configDir := filepath.Dir(configFile)

	log.Printf("配置文件目录: %s", configDir)

	// 创建新的配置映射，避免直接修改原始结构
	newChains := make(map[string]ChainConfig)

	for chainID, chainConfig := range GlobalConfig.Chains {
		log.Printf("处理链 %s 的配置", chainID)

		// 修正连接文件路径
		profilePath := chainConfig.Connection.Profile
		log.Printf("原始连接路径: %s", profilePath)

		if profilePath != "" {
			if !filepath.IsAbs(profilePath) {
				absPath := filepath.Join(configDir, profilePath)
				log.Printf("转换为绝对路径: %s", absPath)
				chainConfig.Connection.Profile = absPath
			}
		}

		newChains[chainID] = chainConfig
	}

	GlobalConfig.Chains = newChains
}

// 初始化配置（支持热加载）
func Init(configPath string) error {
	// 设置配置文件路径和类型
	viper.SetConfigType("yaml")
	if configPath != "" {
		viper.SetConfigFile(configPath)
	} else {
		viper.SetConfigName("config")
		viper.AddConfigPath("./config")
		viper.AddConfigPath(".")
	}

	// 尝试读取配置
	log.Printf("尝试从 %s 加载配置", configPath)
	if err := viper.ReadInConfig(); err != nil {
		return fmt.Errorf("配置读取失败: %w", err)
	}
	log.Printf("成功加载配置文件: %s", viper.ConfigFileUsed())

	// 解析配置到结构体
	if err := viper.Unmarshal(&GlobalConfig); err != nil {
		return fmt.Errorf("配置解析失败: %w", err)
	}

	// 修正配置中的路径
	resolvePaths()

	// 配置热加载监听
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		log.Println("检测到配置变更:", e.Name)
		if err := viper.Unmarshal(&GlobalConfig); err != nil {
			log.Printf("热加载失败: %v", err)
		} else {
			log.Println("配置热加载成功")
			resolvePaths()
		}
	})

	return nil
}

// 获取有效链配置
func GetActiveChains() map[string]ChainConfig {
	activeChains := make(map[string]ChainConfig)
	for name, cfg := range GlobalConfig.Chains {
		if cfg.IsActive {
			activeChains[name] = cfg
		}
	}
	return activeChains
}

// 获取指定链配置（带校验）
func GetChainConfig(chainName string) (*ChainConfig, error) {
	cfg, exists := GlobalConfig.Chains[chainName]
	if !exists {
		return nil, fmt.Errorf("链[%s]配置不存在", chainName)
	}
	if !cfg.IsActive {
		return nil, fmt.Errorf("链[%s]未激活", chainName)
	}
	return &cfg, nil
}
